using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PETimer;

/// <summary>
/// 阳光系统 - 管理全局阳光生成，包括随机飘下的阳光
/// 使用PETimer定时器模块实现定时生成阳光
/// </summary>
public class SunSystem : ServiceBase
{
    private static SunSystem m_Instance;
    public static SunSystem Instance
    {
        get
        {
            if (m_Instance == null)
            {
                m_Instance = ServiceManager.Instance.GetService<SunSystem>();
            }
            return m_Instance;
        }
    }

    private SunSpawnConfig m_RandomSunConfig;
    private bool m_EnableRandomSun = true;
    private Transform m_SunSpawnArea; // 阳光生成区域
    private bool m_ShowDebugInfo = true;
    private bool m_ShowParabolicDebug = false;
    
    // 定时器相关
    private TickTimer m_Timer; // 使用TickTimer实现毫秒级精确定时
    private int m_SunGenerationTaskId = -1; // 阳光生成任务ID
    
    // 保留协程相关用于动画（如果需要）
    private CoroutineRunner m_CoroutineRunner;
    
    /// <summary>
    /// 是否启用随机阳光
    /// </summary>
    public bool EnableRandomSun 
    { 
        get => m_EnableRandomSun; 
        set 
        { 
            m_EnableRandomSun = value;
            if (m_EnableRandomSun && IsInitialized)
            {
                StartRandomSunGeneration();
            }
            else if (!m_EnableRandomSun)
            {
                StopRandomSunGeneration();
            }
        } 
    }
    
    /// <summary>
    /// 随机阳光配置
    /// </summary>
    public SunSpawnConfig RandomSunConfig 
    { 
        get => m_RandomSunConfig; 
        set => m_RandomSunConfig = value; 
    }

    protected override void OnInitialize()
    {
        // 如果没有设置生成区域，使用默认区域
        if (m_SunSpawnArea == null)
        {
            CreateDefaultSpawnArea();
        }
        
        // 如果没有配置，创建默认配置
        if (m_RandomSunConfig == null)
        {
            CreateDefaultConfig();
        }
        
        // 初始化定时器（使用setHandle=true，回调在主线程处理）
        // 因为回调中需要调用Unity API（生成GameObject等），所以需要主线程处理
        m_Timer = new TickTimer(0, true);
        m_Timer.LogFunc = (msg) => Logger.Log("SunSystem Timer", msg);
        m_Timer.WarnFunc = (msg) => Logger.LogWarning("SunSystem Timer", msg);
        m_Timer.ErrorFunc = (msg) => Logger.LogError("SunSystem Timer", msg);
        
        // 注册到全局定时器管理器（因为需要在Unity主线程中更新）
        TimerUpdateComponent.Instance.RegisterTimer(m_Timer);
        
        Logger.Log("SunSystem", "SunSystem 初始化完成（使用PETimer定时器模块）");
    }

    protected override void OnDispose()
    {
        StopRandomSunGeneration();
        
        // 清理定时器
        if (m_Timer != null)
        {
            m_Timer.Reset();
            m_Timer = null;
        }
        
        // 从全局定时器管理器注销
        if (m_Timer != null && TimerUpdateComponent.Instance != null)
        {
            TimerUpdateComponent.Instance.UnregisterTimer(m_Timer);
        }
        
        // 清理协程运行器（用于动画）
        if (m_CoroutineRunner != null)
        {
            if (Application.isPlaying)
            {
                Object.Destroy(m_CoroutineRunner.gameObject);
            }
            m_CoroutineRunner = null;
        }
    }

    /// <summary>
    /// 开始随机阳光生成（使用定时器）
    /// </summary>
    public void StartRandomSunGeneration()
    {
        if (!m_EnableRandomSun || m_RandomSunConfig == null || m_Timer == null)
        {
            return;
        }
        
        // 如果已有任务，先删除
        if (m_SunGenerationTaskId >= 0)
        {
            m_Timer.DeleteTask(m_SunGenerationTaskId);
            m_SunGenerationTaskId = -1;
        }
        
        // 立即生成第一个阳光
        SpawnRandomSun();
        
        // 然后安排下一次生成
        ScheduleNextSunGeneration();
        
        Logger.Log("SunSystem", "开始随机阳光生成（使用PETimer定时器）");
    }

    /// <summary>
    /// 停止随机阳光生成
    /// </summary>
    public void StopRandomSunGeneration()
    {
        if (m_Timer != null && m_SunGenerationTaskId >= 0)
        {
            m_Timer.DeleteTask(m_SunGenerationTaskId);
            m_SunGenerationTaskId = -1;
            Logger.Log("SunSystem", "停止随机阳光生成");
        }
    }
    
    /// <summary>
    /// 安排下一次阳光生成
    /// </summary>
    private void ScheduleNextSunGeneration()
    {
        if (m_Timer == null || m_RandomSunConfig == null || !m_EnableRandomSun)
        {
            return;
        }
        
        // 计算随机间隔（秒转毫秒）
        float intervalSeconds = Random.Range(m_RandomSunConfig.MinInterval, m_RandomSunConfig.MaxInterval);
        uint intervalMs = (uint)(intervalSeconds * 1000);
        
        // 添加定时任务（count=1表示执行一次后自动删除）
        // 这样每次执行后都可以使用新的随机间隔重新安排
        m_SunGenerationTaskId = m_Timer.AddTask(
            intervalMs,
            OnSunGenerationTimerCallback,  // 定时器回调
            OnSunGenerationTimerCancel,    // 取消回调
            1  // count=1表示执行一次后自动删除
        );
        
        if (m_SunGenerationTaskId < 0)
        {
            //Logger.LogError("添加阳光生成定时任务失败！");
        }
        else if (m_ShowDebugInfo)
        {
           // Logger.Log($"安排下一次阳光生成，间隔: {intervalSeconds:F2}秒");
        }
    }
    
    /// <summary>
    /// 阳光生成定时器回调
    /// </summary>
    private void OnSunGenerationTimerCallback(int tid)
    {
        // 在主线程中执行（因为使用了setHandle=true）
        if (m_EnableRandomSun && m_RandomSunConfig != null)
        {
            // 生成阳光
            SpawnRandomSun();
            
            // 任务已自动删除（count=1），重置ID并安排下一次生成（使用新的随机间隔）
            m_SunGenerationTaskId = -1;
            ScheduleNextSunGeneration();
        }
    }
    
    /// <summary>
    /// 阳光生成定时器取消回调
    /// </summary>
    private void OnSunGenerationTimerCancel(int tid)
    {
        if (m_ShowDebugInfo)
        {
            Logger.Log("SunSystem", $"阳光生成定时任务被取消，TID: {tid}");
        }
    }

    /// <summary>
    /// 生成随机阳光
    /// </summary>
    private void SpawnRandomSun()
    {
        if (m_RandomSunConfig == null || m_SunSpawnArea == null) return;
        
        // 计算随机生成位置
        Vector3 spawnPosition = GetRandomSpawnPosition();
        
        // 使用SunPool创建阳光对象
        GameObject sunObject = null;
        
        // 优先使用SunPool
        if (SunPool.Instance != null)
        {
            sunObject = SunPool.Instance.GetSun();
            if (sunObject != null)
            {
                sunObject.transform.position = spawnPosition;
                sunObject.SetActive(true);
            }
        }
        
        // 如果SunPool不可用，使用备用方案
        if (sunObject == null && m_RandomSunConfig.SunPrefab != null)
        {
            sunObject = Object.Instantiate(m_RandomSunConfig.SunPrefab, spawnPosition, Quaternion.identity);
        }
        
        if (sunObject != null)
        {
            // 设置阳光值
            var sunComponent = sunObject.GetComponent<Sun>();
            if (sunComponent != null)
            {
                int sunValue = Random.Range(m_RandomSunConfig.MinSunValue, m_RandomSunConfig.MaxSunValue + 1);
                sunComponent.Initialize(sunValue);
                sunComponent.EnableCollection();
                
                // 添加飘落动画
                AddFallingAnimation(sunObject, spawnPosition);
                
                if (m_ShowDebugInfo)
                {
                    //Logger.Log($"随机生成阳光，价值: {sunValue}，位置: {spawnPosition}");
                }
            }
        }
        else
        {
            // 如果无法创建阳光对象，通过事件系统通知
            int sunValue = Random.Range(m_RandomSunConfig.MinSunValue, m_RandomSunConfig.MaxSunValue + 1);
            var args = ReferencePool.Acquire<SunProducedEventArgs>();
            args.Sun = null; // 没有实际阳光对象
            args.Position = spawnPosition;
            EventHelper.Fire(this, args);
            
            if (m_ShowDebugInfo)
            {
                //Logger.Log($"随机生成阳光 (通过事件)，价值: {sunValue}，位置: {spawnPosition}");
            }
        }
    }

    /// <summary>
    /// 获取随机生成位置
    /// </summary>
    private Vector3 GetRandomSpawnPosition()
    {
        Vector3 basePosition = m_SunSpawnArea.position;
        Vector3 randomOffset = new Vector3(
            Random.Range(-m_RandomSunConfig.SpawnAreaWidth / 2f, m_RandomSunConfig.SpawnAreaWidth / 2f),
            m_RandomSunConfig.SpawnHeight,
            Random.Range(-m_RandomSunConfig.SpawnAreaDepth / 2f, m_RandomSunConfig.SpawnAreaDepth / 2f)
        );
        
        return basePosition + randomOffset;
    }

    /// <summary>
    /// 添加飘落动画
    /// </summary>
    private void AddFallingAnimation(GameObject sunObject, Vector3 startPosition)
    {
        // 计算目标位置（地面）
        Vector3 targetPosition = new Vector3(startPosition.x, 0, startPosition.z);
        
        // 检查配置是否存在
        if (m_RandomSunConfig == null)
        {
            Logger.LogError("SunSystem", "SunSpawnConfig is null! Cannot add falling animation.");
            return;
        }
        
        // 获取或创建协程运行器（延迟初始化）
        CoroutineRunner coroutineRunner = GetOrCreateCoroutineRunner();
        if (coroutineRunner == null)
        {
            Logger.LogError("SunSystem", "无法创建协程运行器！Cannot add falling animation.");
            return;
        }
        
        // 使用协程实现飘落动画
        if (m_RandomSunConfig.EnableParabolicAnimation)
        {
            // 计算抛物线路径，添加随机变化使每个阳光的路径不同
            Vector3[] parabolicPath = CalculateParabolicPathWithVariation(startPosition, targetPosition);
            
            if (parabolicPath == null || parabolicPath.Length < 2)
            {
                //Logger.LogWarning("抛物线路径生成失败，使用直线动画");
                // 降级到直线动画
                coroutineRunner.StartCoroutine(SimpleFallingAnimation(sunObject, startPosition, targetPosition));
            }
            else
            {
                // 使用AnimatedPathWithEasing协程实现路径动画
                if (m_ShowDebugInfo)
                {
                    //Logger.Log($"✓ 启动抛物线动画协程，路径点数: {parabolicPath.Length}, 高度: {m_RandomSunConfig.ParabolaHeight}, 偏移: {m_RandomSunConfig.ParabolaHorizontalOffset}, 持续时间: {m_RandomSunConfig.FallDuration}");
                }
                
                coroutineRunner.StartCoroutine(AnimatedPathWithEasing(sunObject, parabolicPath, m_RandomSunConfig.FallDuration));
            }
        }
        else
        {
            // 使用简单的直线动画
            coroutineRunner.StartCoroutine(SimpleFallingAnimation(sunObject, startPosition, targetPosition));
            
            if (m_ShowDebugInfo)
            {
                //Logger.Log("使用直线动画（EnableParabolicAnimation = false）");
            }
        }
    }
    
    /// <summary>
    /// 计算带随机变化的抛物线路径
    /// </summary>
    private Vector3[] CalculateParabolicPathWithVariation(Vector3 startPos, Vector3 endPos)
    {
        if (m_RandomSunConfig == null) return new Vector3[] { startPos, endPos };
        
        int controlPoints = m_RandomSunConfig.ParabolaControlPoints;
        Vector3[] pathPoints = new Vector3[controlPoints];
        
        // 计算抛物线顶点
        Vector3 midPoint = Vector3.Lerp(startPos, endPos, 0.5f);
        
        // 添加随机高度变化（-50% 到 +100%）
        float heightVariation = m_RandomSunConfig.ParabolaHeight * Random.Range(-0.5f, 1f);
        Vector3 peakPoint = midPoint + Vector3.up * (m_RandomSunConfig.ParabolaHeight + heightVariation);
        
        // 添加随机水平偏移（-100% 到 +100%）
        Vector3 direction = (endPos - startPos).normalized;
        Vector3 rightDirection = Vector3.Cross(direction, Vector3.up).normalized;
        float horizontalVariation = m_RandomSunConfig.ParabolaHorizontalOffset * Random.Range(-1f, 1f);
        peakPoint += rightDirection * (m_RandomSunConfig.ParabolaHorizontalOffset + horizontalVariation);
        
        // 使用二次贝塞尔曲线生成平滑路径
        for (int i = 0; i < controlPoints; i++)
        {
            float t = (float)i / (controlPoints - 1);
            // 使用二次贝塞尔曲线公式：B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
            Vector3 point = (1 - t) * (1 - t) * startPos + 
                            2 * (1 - t) * t * peakPoint + 
                            t * t * endPos;
            pathPoints[i] = point;
        }
        
        return pathPoints;
    }
    
    /// <summary>
    /// 使用自定义缓动曲线的路径动画协程
    /// </summary>
    private IEnumerator AnimatedPathWithEasing(GameObject sunObject, Vector3[] pathPoints, float duration)
    {
        if (pathPoints == null || pathPoints.Length < 2 || sunObject == null)
        {
                Logger.LogWarning("SunSystem", $"AnimatedPathWithEasing: 参数无效 - pathPoints: {pathPoints != null}, length: {(pathPoints != null ? pathPoints.Length : 0)}, sunObject: {sunObject != null}");
            yield break;
        }
        
        if (m_ShowDebugInfo)
        {
            //Logger.Log($"AnimatedPathWithEasing 开始: 路径点数={pathPoints.Length}, 持续时间={duration}, 起点={pathPoints[0]}, 终点={pathPoints[pathPoints.Length - 1]}");
        }
        
        float elapsedTime = 0f;
        
        // 设置初始位置
        sunObject.transform.position = pathPoints[0];
        
        while (elapsedTime < duration && sunObject != null)
        {
            elapsedTime += Time.deltaTime;
            
            // 计算原始进度（0到1）
            float rawProgress = elapsedTime / duration;
            rawProgress = Mathf.Clamp01(rawProgress);
            
            // 使用自定义缓动曲线调整进度
            float easedProgress = m_RandomSunConfig.GetParabolaEasingValue(rawProgress);
            
            // 确保缓动进度在有效范围内
            easedProgress = Mathf.Clamp01(easedProgress);
            
            if (m_ShowDebugInfo && elapsedTime < 0.1f)
            {
                //Logger.Log($"使用自定义缓动曲线: rawProgress={rawProgress:F3}, easedProgress={easedProgress:F3}");
            }
            
            // 根据缓动后的进度在路径上定位
            Vector3 position = GetPositionOnPath(pathPoints, easedProgress);
            
            // 确保位置有效
            if (float.IsNaN(position.x) || float.IsNaN(position.y) || float.IsNaN(position.z))
            {
                Logger.LogWarning("SunSystem", $"计算出的位置包含NaN值: {position}, rawProgress={rawProgress}, easedProgress={easedProgress}");
                position = GetPositionOnPath(pathPoints, rawProgress); // 使用原始进度作为备用
            }
            
            sunObject.transform.position = position;
            
            yield return null;
        }
        
        // 确保到达终点
        if (sunObject != null)
        {
            sunObject.transform.position = pathPoints[pathPoints.Length - 1];
            
            // 启用收集
            var sunComponent = sunObject.GetComponent<Sun>();
            if (sunComponent != null)
            {
                sunComponent.EnableCollection();
            }
        }
    }
    
    /// <summary>
    /// 简单飘落动画协程
    /// </summary>
    private IEnumerator SimpleFallingAnimation(GameObject sunObject, Vector3 startPosition, Vector3 targetPosition)
    {
        float elapsedTime = 0f;
        float duration = m_RandomSunConfig.FallDuration;
        
        // 如果启用抛物线动画，使用抛物线路径（带随机变化）
        Vector3[] pathPoints = null;
        if (m_RandomSunConfig.EnableParabolicAnimation)
        {
            pathPoints = CalculateParabolicPathWithVariation(startPosition, targetPosition);
        }
        
        while (elapsedTime < duration && sunObject != null)
        {
            elapsedTime += Time.deltaTime;
            float rawT = elapsedTime / duration;
            rawT = Mathf.Clamp01(rawT);
            
            // 使用自定义缓动曲线调整进度（如果可用）
            float t = rawT;
            if (m_RandomSunConfig != null && m_RandomSunConfig.ParabolaEasing != null)
            {
                t = m_RandomSunConfig.GetParabolaEasingValue(rawT);
            }
            else
            {
                // 使用默认缓动效果
                t = 1f - (1f - rawT) * (1f - rawT); // Ease.OutQuad
            }
            
            if (pathPoints != null && pathPoints.Length > 0)
            {
                // 使用抛物线路径
                sunObject.transform.position = GetPositionOnPath(pathPoints, t);
            }
            else
            {
                // 使用直线路径
                sunObject.transform.position = Vector3.Lerp(startPosition, targetPosition, t);
            }
            yield return null;
        }
        
        if (sunObject != null)
        {
            sunObject.transform.position = targetPosition;
            var sunComponent = sunObject.GetComponent<Sun>();
            if (sunComponent != null)
            {
                sunComponent.EnableCollection();
            }
        }
    }
    
    /// <summary>
    /// 在路径上获取指定时间点的位置
    /// </summary>
    private Vector3 GetPositionOnPath(Vector3[] pathPoints, float t)
    {
        if (pathPoints == null || pathPoints.Length == 0)
            return Vector3.zero;
            
        if (pathPoints.Length == 1)
            return pathPoints[0];
            
        float segmentLength = 1f / (pathPoints.Length - 1);
        int segmentIndex = Mathf.FloorToInt(t / segmentLength);
        segmentIndex = Mathf.Clamp(segmentIndex, 0, pathPoints.Length - 2);
        
        float localT = (t - segmentIndex * segmentLength) / segmentLength;
        return Vector3.Lerp(pathPoints[segmentIndex], pathPoints[segmentIndex + 1], localT);
    }

    /// <summary>
    /// 创建协程运行器（用于动画）
    /// </summary>
    private void CreateCoroutineRunner()
    {
        // 确保在Unity环境中创建
        if (!Application.isPlaying)
        {
            Logger.LogWarning("SunSystem", "不在运行时环境中，无法创建协程运行器");
            return;
        }
        
        // 如果已存在，先销毁
        if (m_CoroutineRunner != null)
        {
            if (m_CoroutineRunner.gameObject != null)
            {
                Object.Destroy(m_CoroutineRunner.gameObject);
            }
            m_CoroutineRunner = null;
        }
        
        try
        {
            GameObject runner = new GameObject("SunSystemCoroutineRunner");
            m_CoroutineRunner = runner.AddComponent<CoroutineRunner>();
            Object.DontDestroyOnLoad(runner);
            
            if (m_ShowDebugInfo)
            {
                Logger.Log("SunSystem", "✓ SunSystem 协程运行器创建成功");
            }
        }
        catch (System.Exception e)
        {
            Logger.LogError("SunSystem", $"创建协程运行器失败: {e.Message}");
            m_CoroutineRunner = null;
        }
    }
    
    /// <summary>
    /// 获取或创建协程运行器（延迟初始化，用于动画）
    /// </summary>
    private CoroutineRunner GetOrCreateCoroutineRunner()
    {
        if (m_CoroutineRunner == null)
        {
            CreateCoroutineRunner();
        }
        return m_CoroutineRunner;
    }

    /// <summary>
    /// 创建默认生成区域
    /// </summary>
    private void CreateDefaultSpawnArea()
    {
        GameObject spawnArea = new GameObject("SunSpawnArea");
        spawnArea.transform.position = Vector3.zero;
        m_SunSpawnArea = spawnArea.transform;
    }

    /// <summary>
    /// 创建默认配置
    /// </summary>
    private void CreateDefaultConfig()
    {
        m_RandomSunConfig = ScriptableObject.CreateInstance<SunSpawnConfig>();
        m_RandomSunConfig.MinInterval = 5f;
        m_RandomSunConfig.MaxInterval = 15f;
        m_RandomSunConfig.MinSunValue = 15;
        m_RandomSunConfig.MaxSunValue = 25;
        m_RandomSunConfig.SpawnAreaWidth = 20f;
        m_RandomSunConfig.SpawnAreaDepth = 10f;
        m_RandomSunConfig.SpawnHeight = 15f;
        m_RandomSunConfig.FallDuration = 2f;
        
        // 设置抛物线动画参数
        m_RandomSunConfig.EnableParabolicAnimation = true;
        m_RandomSunConfig.ParabolaHeight = 8f;
        m_RandomSunConfig.ParabolaHorizontalOffset = 5f;
        m_RandomSunConfig.ParabolaControlPoints = 12;
    }

    /// <summary>
    /// 立即生成一个随机阳光（用于测试）
    /// </summary>
    [ContextMenu("生成随机阳光")]
    public void SpawnRandomSunImmediately()
    {
        SpawnRandomSun();
    }

    /// <summary>
    /// 设置随机阳光配置
    /// </summary>
    public void SetRandomSunConfig(SunSpawnConfig config)
    {
        m_RandomSunConfig = config;
        if (IsInitialized && m_EnableRandomSun)
        {
            StartRandomSunGeneration();
        }
    }
    
    /// <summary>
    /// 设置抛物线调试显示
    /// </summary>
    public void SetParabolicDebug(bool enabled)
    {
        m_ShowParabolicDebug = enabled;
    }
    
    /// <summary>
    /// 在Scene视图中绘制抛物线路径（仅用于调试）
    /// </summary>
    private void OnDrawGizmos()
    {
        if (!m_ShowParabolicDebug || m_RandomSunConfig == null || m_SunSpawnArea == null)
            return;
            
        // 绘制示例抛物线路径
        Vector3 startPos = m_SunSpawnArea.position + Vector3.up * m_RandomSunConfig.SpawnHeight;
        Vector3 endPos = m_SunSpawnArea.position;
        
        Vector3[] pathPoints = m_RandomSunConfig.CalculateParabolicPath(startPos, endPos);
        
        if (pathPoints != null && pathPoints.Length > 1)
        {
            Gizmos.color = Color.yellow;
            for (int i = 0; i < pathPoints.Length - 1; i++)
            {
                Gizmos.DrawLine(pathPoints[i], pathPoints[i + 1]);
            }
            
            // 绘制路径点
            Gizmos.color = Color.red;
            for (int i = 0; i < pathPoints.Length; i++)
            {
                Gizmos.DrawWireSphere(pathPoints[i], 0.2f);
            }
        }
    }


}
